
/*
 * ndmp_watchdog.c - Wtchdog routines just to make sure that IO is progressing if the state is not idle
 * 
 * This does not use any spin locks as this may be alled from an interrupt context, and other spinlocks may not disable IRQ while locked
 * For now, do not worry about locking the structures
 *
 *      Author: Aboo Valappil
 *      Date: 2/10/2008
 *      Based on: None
 */
#include "ndmp_main.h"

/*
 * ndmp_scsi_watchdog - Triggered from the timer called every NDMP_HBA_TIMEOUT
 *
 */
void ndmp_scsi_watchdog(unsigned long param)
{
        struct ndmp_scsi_session *session = (struct ndmp_scsi_session *)param;
        unsigned long timeout = 0;

// If the sequence number is not progressing and if the IO is in progress, there is a problem. Kill the NDMP thread which will remove the NDMP session
        if ( session->seq_number == session->old_seq_number ) {
                if ( __ndmp_session_state(session, HBA_STATE_CONNECTION) == _NDMP_STAT_IN_PROGRESS ) {
                        printk("ndmphba:%d: NDMP I/O not progressing, connection timed out\n", session->session_id);
                        goto halt_thread;
                }
                if ( __ndmp_session_state(session, HBA_STATE_AUTH) == _NDMP_STAT_IN_PROGRESS ) {
                        printk("ndmphba:%d: NDMP I/O not progressing, authentication timed out\n", session->session_id);
                        goto halt_thread;
                }
                if ( __ndmp_session_state(session, HBA_STATE_DEVICE) == _NDMP_STAT_IN_PROGRESS ) {
                        printk("ndmphba:%d: NDMP I/O not progressing, device open/close timed out\n", session->session_id);
                        goto halt_thread;
                }
                if ( __ndmp_session_state(session, HBA_STATE_THREAD) == _NDMP_STAT_IN_PROGRESS ) {
                        printk("ndmphba:%d: NDMP I/O not progressing, ndmp_thread timed out\n", session->session_id);
                        goto halt_thread;
                }
        }
// If the IO is progressing, refresh the timer
        timeout = NDMP_HBA_TIMEOUT;
        session->old_seq_number =  session->seq_number;
        mod_timer(&session->watchdog_timer, timeout);
        return;

halt_thread:
        printk("ndmphba:%d: Aborting ndmp_thread and closing connections\n", session->session_id);
	kill_ndmp_thread(session);
        return;
}

